package org.acghub.mtdb.core;

import org.acghub.mtdb.common.Pair;
import org.acghub.mtdb.common.exception.LifecycleException;
import org.acghub.mtdb.common.exception.MtdbKeyVerifyException;

import java.util.concurrent.atomic.LongAdder;

/**
 * @author zhouhe
 */
public abstract class AbstractTable<K, V> implements Table<K, V> {

    protected org.acghub.mtdb.common.Table meta;

    protected TableStorage<K, V> storage;

    protected TableCache<K, V> cache;

    protected int tableLockId;

    protected final LongAdder countAdd = new LongAdder();
    protected final LongAdder countAddMiss = new LongAdder();
    protected final LongAdder countAddStorageMiss = new LongAdder();

    protected final LongAdder countFind = new LongAdder();
    protected final LongAdder countFindMiss = new LongAdder();
    protected final LongAdder countFindStorageMiss = new LongAdder();

    protected final LongAdder countRemove = new LongAdder();
    protected final LongAdder countRemoveMiss = new LongAdder();
    protected final LongAdder countRemoveStorageMiss = new LongAdder();

    @Override
    public final org.acghub.mtdb.common.Table meta() {
        return meta;
    }

    @Override
    public final TableCache<K, V> cache() {
        return cache;
    }

    @Override
    public final TableStorage<K, V> storage() {
        return storage;
    }

    @Override
    public final StorageEngine engine() {
        return storage == null ? null : storage.engine();
    }

    @Override
    public void init(Pair<org.acghub.mtdb.common.Table, StorageEngine> pair) throws LifecycleException {
        this.meta = pair.getKey();
        this.tableLockId = Tables.getTableId(meta.getLock());
        TableCacheType.of(Mtdb.INSTANCE.config().getTableCacheType());
    }

    @Override
    public void close() throws LifecycleException {
        cache.close();
        storage.close();
    }

    protected final V find0(K key) {
        return storage != null ? storage.find(key) : null;
    }

    protected final boolean exists0(K key) {
        return storage != null && storage.exists(key);
    }

    protected final boolean verify(K key){
        if (storage == null) {
            return !cache.exists(key);
        }else {
            return storage.verify(key);
        }
    }
}
